home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / xlib06p1.zip / XVSYNC.CPP < prev    next >
C/C++ Source or Header  |  1995-03-19  |  4KB  |  184 lines

  1. #include "xdefs.h"
  2.  
  3. #define TIMER_VECT 0x08
  4.  
  5. #define PIC_CMD         0x20
  6. #define NONSPEC_EOI     0x20
  7. #define TIMER_MODE      0x34
  8. #define TIMER_CONTROL   0x43
  9. #define TIMER_0         0x40
  10.  
  11. #define LATCH_COUNT 0x00
  12.  
  13. #define INT_IN_ADVANCE 0x100
  14.  
  15. #define DOS_GETVECT 0x3500
  16. #define DOS_SETVECT 0x2500
  17.  
  18. WORD _TicksPerSecond;
  19. unsigned long _VsyncIntTicks;
  20. WORD _VsyncPeriod;
  21.  
  22. WORD ClockRate;
  23. WORD ClockCounter;
  24. void ( __interrupt __far *UserVsyncHandler )();
  25. WORD InUserHandler;
  26.  
  27. void * LocalStack;
  28.  
  29. WORD ElapsedVrts;
  30. WORD VrtsToSkip = 1;
  31.  
  32. inline void WaitVsyncStart(
  33.   void
  34. )
  35. {
  36.   while( inp( INPUT_STATUS_0 ) & 0x08 );
  37.   while( !( inp( INPUT_STATUS_0 ) & 0x08 ) );
  38. }
  39.  
  40.  
  41. int get_vsync_period(
  42.   void
  43. )
  44. {
  45.   outp( TIMER_CONTROL, TIMER_MODE );
  46.   outp( TIMER_0, 0 );
  47.   outp( TIMER_0, 0 );
  48.   //now wait for the vertical sync
  49.   WaitVsyncStart();
  50.   outp( TIMER_CONTROL, LATCH_COUNT );
  51.   int iBegin = inp( TIMER_0 );
  52.   iBegin += ( inp( TIMER_0 ) << 8 );
  53.   //now iBegin = 65536 - clicks, so wait for the vsync again
  54.   WaitVsyncStart();
  55.   outp( TIMER_CONTROL, LATCH_COUNT );
  56.   int iEnd = inp( TIMER_0 );
  57.   iEnd += ( inp( TIMER_0 ) << 8 );
  58.   //now iEnd = 65536 - clicks
  59.   //now return iBegin - iEnd to get the change in clicks
  60.   return( iBegin - iEnd );
  61. }
  62.  
  63.   
  64. void __interrupt __far vsync_int(
  65.   void
  66. )
  67. {
  68.   ++VsyncIntTicks;
  69.   ++ElapsedVrts;
  70.   //if there's something to do, do it.
  71.   if ( ElapsedVrts >= VrtsToSkip ) {
  72.     if ( StartAddressFlag != 0 ) {
  73.       outpw( CRTC_INDEX, WaitingStartLow );
  74.       outpw( CRTC_INDEX, WaitingStartHigh );
  75.     }
  76.   }
  77.   //now stop the clock so we can re-sync
  78.   _disable();
  79.   outp( TIMER_CONTROL, TIMER_MODE );
  80.   outp( TIMER_0, 255 );
  81.   outp( TIMER_0, 255 );
  82.   //now wait for the vsync again...
  83.   while( inp( INPUT_STATUS_0 ) & 0x08 );
  84.   //now restart yon clock...
  85.   outp( TIMER_CONTROL, TIMER_MODE );
  86.   outp( TIMER_0, ClockRate & 0xff );
  87.   outp( TIMER_0, ClockRate >> 8 );
  88.   //more checks on "if there's something to do..."
  89.   if ( ElapsedVrts >= VrtsToSkip ) {
  90.     if ( StartAddressFlag != 0 ) {
  91.       ElapsedVrts = 0;
  92.       outp( AC_INDEX, WaitingPelPan & 0xff );
  93.       outp( AC_INDEX, WaitingPelPan >> 8 );
  94.       StartAddressFlag = 0;
  95.     }
  96.   }
  97.   //check for a palette update
  98.   if ( VsyncPaletteCount != 0 ) {
  99.     outp( DAC_WRITE_INDEX, VsyncPaletteStart & 0xff );
  100.     BYTE * pbDacData = VsyncPaletteBuffer + VsyncPaletteStart;
  101.     for ( int i = 0; i < VsyncPaletteCount; ++i ) {
  102.       outp( DAC_DATA, *pbDacData++ );
  103.       outp( DAC_DATA, *pbDacData++ );
  104.       outp( DAC_DATA, *pbDacData++ );
  105.     }
  106.     VsyncPaletteCount = 0;
  107.   }
  108.   //check for a mouse update
  109.   if ( MouseRefreshFlag != 0 ) {
  110.     MouseVsyncHandler();
  111.   }
  112.   //check for a user vsync handler
  113.   if ( UserVsyncHandler != NULL ) {
  114.     if ( InUserHandler == 0 ) {
  115.       SetStack(...)
  116.       _enable();
  117.       UserVsyncHandler();
  118.       _disable();
  119.       InUserHandler = 0;
  120.     }
  121.   }
  122.   //now simulate the 18.2 Hz timer handler
  123.   ClockCounter += VsyncPeriod;
  124.   if ( ClockCounter >= 65536 ) {
  125.     _enable();
  126.     OldTimerInt();
  127.     ClockCounter -= 65536;
  128.   }
  129.   outp( PIC_CMD, NONSPEC_EOI );
  130.   _enable();
  131. }
  132.  
  133.  
  134. void x_install_vsync_handler(
  135.   int iVrtSkipCount
  136. )
  137. {
  138.   if ( iVrtSkipCount <= 0 ) {
  139.     iVrtSkipCount = 0;
  140.   }
  141.   VrtsToSkip = iVrtSkipCount;
  142.   ElapsedVrts = 0;
  143.   if ( VsyncHandlerActive == TRUE ) {
  144.     return;
  145.   }
  146.   int iPeriod = get_vsync_period;
  147.   VsyncPeriod = iPeriod;
  148.   iPeriod -= INT_IN_ADVANCE;
  149.   ClockRate = iPeriod;
  150.   
  151.   TicksPerSecond = 13352 / VsyncPeriod;
  152.   _disable();
  153.   OldTimerInt = dos_getvect( TIMER_VECT );
  154.   VsyncHandlerActive = TRUE;
  155.   dos_setvect( TIMER_VECT, vsync_int );
  156.   outp( TIMER_CONTROL, TIMER_MODE );
  157.   outp( TIMER_0, ClockRate & 0xff );
  158.   outp( TIMER_0, ClockRate >> 8 );
  159. }
  160.  
  161. void x_remove_vsync_handler(
  162.   void
  163. )
  164. {
  165.   if ( VsyncHandlerActive == FALSE ) {
  166.     return;
  167.   }
  168.   _disable();
  169.   dos_setvect( TIMER_VECT, OldTimerInt );
  170.   outp( TIMER_CONTROL, TIMER_MODE );
  171.   outp( TIMER_0, 0 );
  172.   outp( TIMER_0, 0 );
  173.   _enable();
  174. }
  175.  
  176. void x_set_user_vsync_handler(
  177.   void ( __interrupt __far *pvHandlerProc )()
  178. )
  179. {
  180.   _disable();
  181.   UserVsyncHandler = pvHandlerProc;
  182.   _enable();
  183. }
  184.